#include "Car.h"
#include "SDL.h"
#define _USE_MATH_DEFINES
#include <cmath>

#include "PlayState.h"

#include <SDL_OpenGL.h>
#include <GL/glut.h>

Car::Car()
{
	m_acc = 0;
	m_angle = 270.0f;
	m_moving = true;
	m_rotating = true;
	m_speedPressed = 0;
	m_keyBoardMovingUp = false;
	m_keyBoardMovingDown = false;
	m_keyBoardRotating = false;
}
void Car::Update()
{
	float dt = TheTimer::Instance()->GetDt();
	Vec3f oldVel = m_vel;
	m_vel += oldVel * m_acc * dt;
	m_pos += m_vel * 0.5 * dt;

	float xSpeed = Car::GetVel().GetX();
	if(xSpeed < 0)
	{
		xSpeed = -xSpeed;
	}

	float zSpeed = Car::GetVel().GetZ();
	if(zSpeed < 0)
	{
		zSpeed = -zSpeed;
	}
	//speed the car is moving relavive to both x and z axis
	float actualSpeed =  xSpeed + zSpeed;

	//this means that the car cannot rotate on the spot
	//rotational angle will depend on the speed the car is moving at
	float rotComponent = ( 0.1 *( actualSpeed));

	//angle is calculated on joypad direction multiplied by speed
	m_angle += (((m_rotVel/180.0f) * M_PI * dt) * rotComponent);

	float speed = 20.0f;
	//flag to control wheel rotation 
	if (m_rotating == true || m_keyBoardRotating == true)
	{
		if(m_moving == true)
		{
			TheCar::Instance()->SetVel( Vec3f((cosf(-m_angle * M_PI/180)* -m_speedPressed), 0, (-sinf(m_angle * M_PI/180)* -m_speedPressed)));			
		}
		if(m_keyBoardMovingUp == true)
		{
			TheCar::Instance()->SetVel( Vec3f((cosf(m_angle * M_PI/180)* speed), 0, (-sinf(m_angle * M_PI/180)* speed)));
		}
		else
		{
			//			TheCar::Instance()->SetVel( Vec3f((-(cosf(m_angle * M_PI/180)* speed), 0, (-sinf(m_angle * M_PI/180)* speed))));
		}
		if(m_keyBoardMovingDown == true)
		{
			TheCar::Instance()->SetVel(( Vec3f((cosf(m_angle * M_PI/180)* -speed), 0, (-sinf(m_angle * M_PI/180))* -speed )));
		}
		else
		{
			//			TheCar::Instance()->SetVel(( Vec3f((-(cosf(m_angle * M_PI/180)* -speed), 0, (-sinf(m_angle * M_PI/180))* -speed ))));
		}


	}

}
Vec3f& Car::GetPos()
{
	return m_pos;
}
void Car::SetPos(const Vec3f& pos)
{
	m_pos = pos;
}

Vec3f& Car::GetVel()
{
	return m_vel;
}
bool Car::Load(const std::string& filename, const std::string& tyreName)
{
	m_car.Load(filename);
	for(int i = 0; i < 4; ++i)
		m_wheels[i].Load(tyreName);

	//Front left
	m_wheelTransforms[0] = Vec3f(4,0,4);
	//Front right
	m_wheelTransforms[1] = Vec3f(-4,0,4);
	//Back left
	m_wheelTransforms[2] = Vec3f(4,0,-4);
	//Back right
	m_wheelTransforms[3] = Vec3f(-4,0,-4);
	return true;
}
void Car::Draw()
{
	//push matrix to draw the car
	glPushMatrix();
		glColor3f(1.0f, 1.0f, 1.0f);
		glTranslatef(m_pos.GetX(), m_pos.GetY(), m_pos.GetZ());
		glRotatef(m_angle,0,1,0);//change this angle to degrees
		//draw the car itself
		m_car.Draw();

		//Now Draw the Tyres
		for(int i = 0; i < 4; ++i)
		{
			glPushMatrix();
			glTranslatef(m_wheelTransforms[i].GetX(),m_wheelTransforms[i].GetY(),m_wheelTransforms[i].GetZ());
				m_wheels[i].Draw(); //draw the front left wheel
			glPopMatrix();
		}

	glPopMatrix();

	//shadow under the car
	glPushMatrix();
		glDisable(GL_LIGHTING);
		glTranslatef(GetPos().GetX(),-0.5F, GetPos().GetZ());
		glScalef(0.8F,0.0F,0.8F);
		glColor3f(0.0F,0.0F,0.0F);
		glutSolidSphere((.9f -((m_pos.GetY()+15)/50)), 10,10);
		glEnable(GL_LIGHTING);
	glPopMatrix();

}
void Car::OnKeyboardEvent(const SDL_KeyboardEvent& event)
{
	float speed = 20.0f;

	if(event.state == SDL_PRESSED)
	{
		switch (event.keysym.sym)
		{
		case SDLK_UP :
			{
				TheCar::Instance()->SetVel( Vec3f((cosf(m_angle * M_PI/180)* speed), 0, (-sinf(m_angle * M_PI/180)* speed)));
				m_keyBoardMovingUp = true;
				break;
			}
		case SDLK_DOWN :
			{
				TheCar::Instance()->SetVel(( Vec3f((cosf(m_angle * M_PI/180)* -speed), 0, (-sinf(m_angle * M_PI/180))* -speed )));
				m_keyBoardMovingDown = true;
				break;
			}
		case SDLK_LEFT ://turn left ccw
			{
				m_rotVel = math::degToRad(30);
				m_keyBoardRotating = true;
				break;
			}
		case SDLK_RIGHT ://turn right cw
			{
				m_rotVel = math::degToRad(-30);
				m_keyBoardRotating = true;
				break;
			}
		}
	}

	else if(event.state == SDL_RELEASED)
	{
		switch (event.keysym.sym)
		{
		case SDLK_UP :
			{
				TheCar::Instance()->SetVel( Vec3f(0, 0, 0));
				m_keyBoardMovingUp = false;
				break;
			}
		case SDLK_DOWN :
			{
				TheCar::Instance()->SetVel( Vec3f(0,0,0));
				m_keyBoardMovingDown = false;
				break;
			}
		case SDLK_LEFT ://turn left ccw
			{
				m_rotVel = math::degToRad(0);
				m_keyBoardRotating = false;
				m_rotating = false;
				break;
			}
		case SDLK_RIGHT ://turn right cw
			{
				m_rotVel = math::degToRad(0);
				m_keyBoardRotating = false;
				m_rotating = false;
				break;
			}
		}
	}
}
void Car::OnJoystickAxisEvent(const SDL_JoyAxisEvent& event)
{

	// Consistent speed for player velocity
	float speed = 10.0f;

	if (event.axis == 2)
	{
		m_speedPressed = ( event.value / 1000);

		if(event.value > 100)
		{
			TheCar::Instance()->SetVel( Vec3f((cosf(m_angle * M_PI/180)* -m_speedPressed), 0, (-sinf(m_angle * M_PI/180)* -m_speedPressed)));
			m_moving = true;
		}
		else if(event.value < -100)
		{	
			TheCar::Instance()->SetVel( Vec3f((cosf(-m_angle * M_PI/180)* -m_speedPressed), 0, (-sinf(m_angle * M_PI/180)* -m_speedPressed)));
			m_moving = true;
		}
		else
		{
			TheCar::Instance()->SetVel( Vec3f(0,0,0));
			m_moving = false;
		}
	}



	//rotate left and right
	// X axis Trigger point, Dead Zone and Stop State
	if (event.axis == 0)
	{
		if (event.value > 20000)
		{
			m_rotVel = math::degToRad(-30);
			m_rotating = true;
		}
		else if (event.value < -20000)
		{
			m_rotVel = math::degToRad(30);
			m_rotating = true;
		}
		else
		{
			m_rotVel = 0;
			m_rotating = false;
		}
	}

}
void Car::SetVel(Vec3f vel)
{
	m_vel = vel;
}
void Car::Direction()
{
	m_angle = ((m_angle/M_PI)*180);
}
void Car::Unload()
{
	m_car.Unload();
	for(int i = 0; i < 4; ++i)
	{
		m_wheels[i].Unload();
	}
}